home *** CD-ROM | disk | FTP | other *** search
- ;
- ; 08h interrupt driver (from BYTE special issue, nov. 86, pp 249-262)
- ;
- ; Adaptation: Marc Savary, Ad Lib Inc, 1986/11/03
- ;
-
- ; This module allows you to change the timer-0 interrupt rate,
- ; without affecting the rate at which the currently installed
- ; routine is called ( 18.2 Hz).
- ;
- ; A user function (TimeOut()) is called after 'n'
- ; interrupts, 'n' being reset after each call.
-
-
- ; Originally written for Lattice C Compiler, small model. Adapted to
- ; Microsoft by using macros (notably BEGIN, P_END, EXTERN). A flag for the
- ; type of compiler is defined in the file VERSION.INC. According to this
- ; flag, the file containing the appropriate equates and macros is then
- ; included.
-
- INCLUDE VERSION.INC ;*** compilation flags are defined in this file ***
-
- IF MICROSOFT
- INCLUDE CMICRO.MAC ;memory model & equates for Microsoft environment
- ELSE
- INCLUDE DOS.MAC ;memory model & equates for Lattice environment
- ENDIF
-
- INCLUDE COMMON.MAC ;macros common to both environments
-
-
- clk_int equ 08h ; timer-0 interrupt vector number
-
-
- ; ============= vector structure ==========
-
- vector struc
- regip dw ?
- regcs dw ?
- vector ends
-
-
- ; ========================= DATA SEGMENT ============================
-
- DSEG
-
- int_stack_size equ 512
-
- the_stack db int_stack_size DUP ('S')
- interrupt_stack_top dw 0
-
- ENDDS
-
-
- ;========================== CODE SEGMENT ============================
-
- IF MICROSOFT
- PSEG <TIMER>
- ELSE
- PSEG
- ENDIF
-
- EXTERN TimeOut
-
-
- clkdivh dw ? ; actual divisor ... high
- clkdivl dw ? ; ... low
- clkmod dw ? ; divisor modulus
-
- int08 vector <>
-
- appl_ds dw ?
- old_ss dw ? ; interrupted code's SS
- old_sp dw ? ; SP .......
-
- soundDelay dw ? ; delay counter
- user_routine_on db (?) ; flag to avoid reentrance
-
-
-
-
- ; clkrate()
- ;
- ; change timer-0 divider
- ; IN : AX count divisor
- ;
- IF LPROG
- clkrate proc FAR
- ELSE
- clkrate proc NEAR
- ENDIF
- ; load counter 0 of 8253:
- push ax
- mov al, 00110110b ; square wave mode
- out 43h, al
- pop ax
- out 40h, al
- xchg ah, al
- out 40h, al
- xchg ah, al
- ret
- clkrate endp
-
-
- ; _SetInt( state)
- ;
- ; enable/disable CPU interrupt.
- ;
- BEGIN SetInt
-
- Sintframe struc
- dw (?)
- db CPSIZE DUP (?)
- state dw (?) ; interrupt state
- Sintframe ends
- push bp
- mov bp, sp
-
- cmp [ bp].state, 0
- jne s_on
- ; off:
- cli
- jmp s_end
- s_on:
- sti
- s_end:
- pop bp
- ret
-
- P_END SetInt
-
-
-
-
- ; _SetClkRate( unsigned count)
- ;
- ; Initialize interrupt rate to (1.119 MHz / count) cycles/sec.
- ;
- BEGIN SetClkRate
-
- scrframe struc
- dw (?)
- db CPSIZE DUP (?)
- divid dw (?) ; timer's divider
- scrframe ends
- push bp
- mov bp, sp
-
- mov ax, [ bp].divid
- pushf
- cli
- mov CS:clkdivl, ax
- cmp ax, 1
- mov CS:clkdivh, 0
- adc CS:clkdivh, 0
- call clkrate
- popf
- pop bp
- ret
- P_END SetClkRate
-
-
-
- ; Install clock-driver (soft int-08, timer-0).
- ; Save a copy of DS.
- ;
- BEGIN clk_install
-
- ; install clock interrupt handler
- push ax
- push dx
-
- ; init. clk variables:
- xor ax, ax
- call clkrate
- mov CS:clkdivh, 1
- mov CS:clkdivl, ax
- mov CS:clkmod, ax
-
- ; init flag:
- mov cs:user_routine_on, 0
-
- ; save application DS:
- mov ax, ds
- mov cs:appl_ds, ax
-
- ; save current int. vector
- push es
- mov ah, 35h
- mov al, clk_int
- int 21h ; get old vector
- assume es:nothing
- mov CS:int08.regip, bx
- mov CS:int08.regcs, es
- pop es
- ; install interrupt intercept vector:
- push ds
- mov ah, 25h
- mov al, clk_int
- mov dx, offset clkint
- mov bx, CS
- mov ds, bx
- int 21h ; set int. vector
- pop ds
- pop dx
- pop ax
-
- ret
- P_END clk_install
-
-
-
- ; _clk_uninstall()
- ;
- BEGIN clk_uninstall
-
- xor ax, ax
- call clkrate
- ; reset int. vector:
- push ds
- mov ah, 25h
- mov al, clk_int
- lds dx, CS:int08
- int 21h ; set vector ...
- pop ds
- ret
- P_END clk_uninstall
-
-
-
-
- ; _StartTimeOut( delay)
- ;
- ; Initialize count-down delay to 'delay'.
- ;
-
- BEGIN StartTimeOut
-
- istad struc
- dw (?)
- db CPSIZE DUP (?)
- delay dw (?) ; delay before doing the next call
- istad ends
-
- push bp
- mov bp, sp
- pushf
- cli
- mov ax, [ bp].delay
- mov cs:soundDelay, ax
- popf
- pop bp
- ret
-
- P_END StartTimeOut
-
-
-
- ; clkint
- ;
- ; int-08 Interrupt Driver routine.
- ;
- ; Check for roll-over of 65536 cycles ( 18.2 hz ) and call
- ; old driver if so.
- ;
- ; Count-down delay variable, and if zero, call routine 'TimeOut()'
- ; & set the new delay.
- ;
- clkint proc FAR
-
- push ax
-
- ; check for roll-over of 65536 cycles ( 18.2 hz )
- mov ax, CS:clkdivl
- add CS:clkmod, ax
- mov ax, CS:clkdivh
- adc ax, 0
- jnz clkint8
- ; not yet time, skip original interrupt
- mov al, 00100000b
- out 20h, al ; 8259 ...
- jmp clkint7
- ; do the original interrupt:
- clkint8 label near
- pushf
- call CS:int08
-
- clkint7 label near
-
- dec CS:soundDelay ; 16 bits unsigned counter
- jnz clkint_end
-
- ; to avoid a reentrant call
- cmp CS:user_routine_on, 0
- jnz clkint_end ; already active ...
-
- ; end of delay. Prepare environment before calling TimeOut()
- ; (allocate temporary stack, set segment registers).
- ;
-
- ; save all registers...
- push bx
- push cx
- push dx
- push ds
- push es
- push si
- push di
- push bp
-
- ; save active stack pointers
- mov cs:old_ss, ss
- mov cs:old_sp, sp
-
- ; get application's DS
- mov ax, cs:appl_ds
- mov es, ax
- mov ds, ax
-
- ; set new stack:
- mov ss, ax
- mov sp, offset DGROUP:interrupt_stack_top
-
-
- go_user label near
- public go_user
-
- ; protect call with flag
- inc CS:user_routine_on
-
- ; call the C routine
- sti
- IF MICROSOFT
- call _TimeOut ; time-out driver ... ==> AX: new delay
- ELSE
- call TimeOut ; time-out driver ... ==> AX: new delay
- ENDIF
-
- cli
- ;
- dec CS:user_routine_on
-
- ; compute new delay
- mov bx, CS:soundDelay
- neg bx ; # of interrupt since call to TimeOut()
- cmp bx, ax ; time-out ?
- jb clk_delay_ok ; no ...
-
- ; we must recall TimeOut immediately
- mov CS:soundDelay, 0
- jmp go_user
-
- clk_delay_ok label near
- add CS:soundDelay, ax ; leftover delay count
-
- ; restore stack
- mov bx, CS:old_ss
- mov ss, bx
- mov sp, CS:old_sp
-
- sti
-
- pop bp
- pop di
- pop si
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
-
- clkint_end label near
- pop ax
- iret
- clkint endp
-
-
- IF MICROSOFT
- ENDPS <TIMER>
- ELSE
- ENDPS
- ENDIF
-
- end
-